from common.common import output_result_file, report_job_details
from common.common_models import SubJobDetails, LogDetail, CopyInfoRepModel, Copy
from common.const import SubJobStatusEnum, ExecuteResultEnum
from common.parse_parafile import ParamFileUtil

from exchange.common.const import ActionResponse, ExchangeCode, ExchangeSubJobName, LogLevel, JobInfo, ErrorCode
from exchange.common.exchange_backup_exception import LogDetailException
from exchange.handle.backup.exec_backup import BackUp
from exchange.logger import log

class ExchangeBackupService(object):
    """
    备份任务相关接口
    """
    @staticmethod
    def exec_backup(req_id, job_id, sub_id, json):
        response = ActionResponse()
        log.info(f'step 6: start to execute backup, req_id: {req_id}, job_id: {job_id},sub_id:{sub_id}')
        file_content = ExchangeBackupService.safe_get_info(req_id)
        sub_job_name = file_content.get("subJob", {}).get("jobName", "")
        backup_inst = BackUp(req_id, job_id, sub_id, json, file_content)
        exec_backup_func_dict = {
            ExchangeSubJobName.SUB_EXEC_MOUNT_JOB: backup_inst.exec_mount_job,
            ExchangeSubJobName.SUB_EXEC_DATA_BACKUP: backup_inst.exec_data_backup_sub_job,
        }
        try:
            ret = exec_backup_func_dict.get(sub_job_name)()
        except LogDetailException as err_expected:
            log_detail = err_expected.log_detail
            ExchangeBackupService.set_error_response(response)
            ExchangeBackupService.report_error_job_details(job_id, req_id, response, sub_id, log_detail)
            return False
        except Exception as err_unexpected:
            log.error(f"exec_backup failed: {sub_job_name} : {err_unexpected}")
            ExchangeBackupService.set_error_response(response)
            ExchangeBackupService.report_error_job_details(job_id, req_id, response, sub_id)
            return False

        if sub_job_name == ExchangeSubJobName.SUB_EXEC_DATA_BACKUP :
            if not ret[0]:
                ExchangeBackupService.set_error_response(response)
                ExchangeBackupService.report_error_job_details(job_id, req_id, response, sub_id)
                return False
            total_dir_size, speed = ret[1], ret[2]
        else:
            if not ret:
                ExchangeBackupService.set_error_response(response)
                ExchangeBackupService.report_error_job_details(job_id, req_id, response, sub_id)
                return False
            total_dir_size, speed = 0, 0
        response = ActionResponse(code=ExecuteResultEnum.SUCCESS)
        output_result_file(req_id, response.dict(by_alias=True))
        log.info(f"exec_backup_success, total_dir_size {total_dir_size}, speed {speed}")
        log_detail = LogDetail(logInfo="plugin_task_subjob_success_label",
                               logInfoParam=[sub_id], logLevel=LogLevel.INFO)
        report_job_details(req_id, SubJobDetails(taskId=job_id, subTaskId=sub_id, progress=100,
                                                 logDetail=[log_detail], dataSize=total_dir_size, speed=speed,
                                                 taskStatus=SubJobStatusEnum.COMPLETED.value))
        log.info(f"exec_backup end")
        return True



    @staticmethod
    def set_error_response(response):
        response.code = ExchangeCode.FAILED.value
        response.body_err = ExchangeCode.FAILED.value

    @staticmethod
    def report_error_job_details(job_id, req_id, response, sub_id, log_detail=None):
        if log_detail is None:
            log_detail = LogDetail(logInfo="plugin_task_subjob_fail_label", logInfoParam=[sub_id],
                                   logLevel=LogLevel.ERROR)
        if response != ExchangeCode.SUCCESS.value:
            log.info(f'report_sub_job_details:{response}')
            report_job_details(req_id, SubJobDetails(taskId=job_id, subTaskId=sub_id, progress=100,
                                                     logDetail=[log_detail], taskStatus=SubJobStatusEnum.FAILED.value))


    @staticmethod
    def safe_get_info(pid):
        # 通过pid读取到相应的参数文件
        try:
            param = ParamFileUtil.parse_param_file(pid)
        except Exception as err:
            raise Exception(f"Failed to parse job param file for {err}") from err
        if not param:
            raise Exception(f"Failed to parse job param file is none")
        return param

